home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / test.el / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-09-08  |  63.7 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i038:  Test system for GNU Emacs, Part03/03
  5. Message-ID: <1503@uunet.UU.NET>
  6. Date: 10 Sep 87 03:54:52 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1722
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: "Mark A. Ardis" <maa@sei.cmu.edu>
  12. Posting-number: Volume 11, Issue 38
  13. Archive-name: test.el/Part03
  14.  
  15.  
  16. #! /bin/sh
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create:
  21. #    MANIFEST
  22. #    test.texinfo
  23. export PATH; PATH=/bin:/usr/bin:$PATH
  24. echo shar: "extracting 'MANIFEST'" '(1149 characters)'
  25. if test -f 'MANIFEST'
  26. then
  27.     echo shar: "will not over-write existing file 'MANIFEST'"
  28. else
  29. sed 's/^X//' << \SHAR_EOF > 'MANIFEST'
  30. XFile                    Archive         Description
  31. X----                    -------         -----------
  32. XMANIFEST                   1            This file
  33. Xbox.script                 2            Example test script
  34. Xexample.texinfo            2            Appendix part of user manual
  35. Xhooks.el                   2            Example hooks for customization
  36. Xtest.el                    2            Root of test package
  37. Xtest.texinfo               1            Main part of user manual
  38. Xtst-achieve.el             2            Achieve-state routines
  39. Xtst-analyze.el             2            Analyze test results
  40. Xtst-annotate.el            2            Annotate package with results
  41. Xtst-capture.el             2            Capture-state routines
  42. Xtst-display.el             3            Display test results
  43. Xtst-equal.el               3            Test states for equality
  44. Xtst-inequal.el             3            Modifications to notion of equality
  45. Xtst-instrument.el          3            Instrument package for testing
  46. Xtst-utilities.el           2            Miscellaneous utilities
  47. Xuser.texinfo.el            2            Wrapper for hard-copy user manual
  48. SHAR_EOF
  49. if test 1149 -ne "`wc -c < 'MANIFEST'`"
  50. then
  51.     echo shar: "error transmitting 'MANIFEST'" '(should have been 1149 characters)'
  52. fi
  53. fi
  54. echo shar: "extracting 'test.texinfo'" '(60887 characters)'
  55. if test -f 'test.texinfo'
  56. then
  57.     echo shar: "will not over-write existing file 'test.texinfo'"
  58. else
  59. sed 's/^X//' << \SHAR_EOF > 'test.texinfo'
  60. X@setfilename test
  61. X@node top, introduction, , (dir)
  62. X@ifinfo
  63. XThere should be more nodes than listed below, but at least the chapters are
  64. Xisolated.
  65. X@menu
  66. X* introduction::    Purpose of the package.
  67. X* starting::        How to get started.
  68. X* testing::        Testing a package.
  69. X* instrumenting::    Instrumenting to measure testing effectiveness.
  70. X* analyzing::        Analyzing the results of testing.
  71. X* displaying::        Displaying the results of analysis.
  72. X* running::        Running a testscript in batch.
  73. X* epilogue::        Final words.
  74. X* example::        An example package to test.
  75. X@end menu
  76. X@end ifinfo
  77. X@node introduction, starting, , top
  78. X
  79. X@chapter Introduction
  80. X
  81. XThis document explains how to use the Test package to test GNU Emacs
  82. Xpackages.  It is an extension of Chapter 22 [Compiling and Testing
  83. XPrograms] of the GNU Emacs Reference Manual.
  84. X
  85. X@section Purpose of the Package
  86. X
  87. XThis package provides tools to aid in developing regression tests for Emacs
  88. Xpackages and to assess the efficacy of those tests.  GNU Emacs packages,
  89. Xwritten in a dialect of Lisp, provide extensions to the basic text editing
  90. Xfeatures of Emacs.  Most of these packages perform state-changing
  91. Xoperations.  For example, a package may create new buffers, modify text,
  92. Xchange the locations of the cursor and various marks, write files or modify
  93. Xanything else accessible to Emacs (which is just about everything in Unix).
  94. XTraditional Lisp debugging strategies are not sufficient to adequately test
  95. Xa package that performs extensive state-manipulation.  The Test package
  96. Xprovides a strategy that is.
  97. X
  98. X@section Test Approach
  99. X
  100. XThe Test system is designed to support structural (or ``white-box'')
  101. Xtesting.  (Another commonly used test approach is functional, or
  102. X``black-box'' testing.)  It automates the process of running a number of
  103. Xtests cases designed to analyze ``coverage'' of the package (that is, find
  104. Xparts of the code that are not exercised) and ``expression'' (that is, what
  105. Xvalues are returned by each expression, and which expressions always
  106. Xreturned the same values).
  107. X
  108. X@section Testing Method
  109. X
  110. XTest provides mechanisms to ease the creation and execution of sets of
  111. Xtests.  Some of the features are designed to simplify testing activity,
  112. Xwhile others are designed to aid the analysis of testing.
  113. X
  114. XTest supports coverage testing.  That is, it provides instrumentation
  115. Xmechanisms designed to check for inadequacies of testing of the following
  116. Xtwo forms:
  117. X@itemize @bullet
  118. X@item
  119. XFailure to execute an expression.
  120. X@item
  121. XFailure to produce more than one value for an expression.
  122. X@end itemize
  123. XIn each case, the fault may be in the tests (i.e., not enough testing was
  124. Xperformed), or the fault may be in the program (i.e., an ``unnecessarily
  125. Xcomplex'' program has been written).  (There is also the possibility that
  126. Xno fault exists, such as the use of ``constant'' functions for readability
  127. Xor style.  In practice these cases are easy to identify and ignore.)
  128. X
  129. XYou should use the following strategy in creating tests with this
  130. Xsystem:
  131. X@enumerate
  132. X@item
  133. XCreate a simple set of tests that appear to be necessary to test the basic
  134. Xfunctionality of the package.
  135. X@item
  136. XAdd additional tests to ensure that every expression is executed, and that
  137. Xeach expression produces at least two values over the entire set of tests.
  138. X@item
  139. XRun the set of tests with instrumentation to check for inadequacies.
  140. X@item
  141. XIf there are reported inadequacies, then correct the code or improve the
  142. Xtesting, and go back to the previous step.
  143. X@end enumerate
  144. XThere is no guarantee that a set of tests that passes these coverage checks
  145. Xwill find all errors.  But, such a set of tests has the property that every
  146. Xexpression in the code has been exercised in a minimally significant way
  147. X(i.e., every expression has produced at least two different values).  In
  148. Xpractice, a great number of errors can be detected with this method.
  149. X
  150. XThe importance of coverage testing increases as a package is modified.
  151. XChanges to one part of a package may have unexpected effects on other
  152. X(unconsidered) parts.  Coverage testing ensures that all parts of a package
  153. Xare tested, at least minimally.  Coverage tests also serve as a
  154. Xspecification of the functionality of a package.
  155. X
  156. XFigure 1 illustrates the overall flow of events using this test
  157. Xapproach.
  158. X
  159. X@group
  160. X@example
  161. X        +------------+                         +--------------+
  162. X        | Instrument |                         | Generate     |
  163. X        | o Control  |                         | o Test Cases |
  164. X        | o Data     |                         | o Script(s)  |
  165. X        +------------+                         +--------------+
  166. X                      \                       /     ^
  167. X                       \                     /      |
  168. X                        \                   /       |
  169. X                         \                 /        |
  170. X                          \               /         |
  171. X                           \             /          |
  172. X                           +-------------+          |
  173. X                           |   Execute   |          |
  174. X                           |     the     |          |
  175. X                           |   Test(s)   |          |
  176. X                           +-------------+          |
  177. X                                  |                 |
  178. X                                  |                 |
  179. X                           +-------------+          |
  180. X                           |   Analyze,  |          |
  181. X                           |   Display   |          |
  182. X                           |   Results   |          |
  183. X                           +-------------+          |
  184. X                                  |                 |
  185. X                                  |                 |
  186. X                                  ^                 |
  187. X                                /   \               |
  188. X                               /     \  No          |
  189. X                              < Done? >-------------+
  190. X                               \     /
  191. X                                \   /
  192. X                                 \ /
  193. X                                  v
  194. X                                  | Yes
  195. X                                  |(Test Goals Achieved)
  196. X                                  V
  197. X
  198. X
  199. X
  200. X@end example
  201. X@center Figure 1.  General Test Algorithm
  202. X@end group
  203. X
  204. X@section Overview
  205. X
  206. XThe Test product consists of four major subsystems:
  207. X@itemize @bullet
  208. X@item
  209. XRegression Subsystem -- a set of functions to support regression testing of
  210. XEmacs packages.
  211. X@item
  212. XCoverage Subsystem -- a set of functions to support coverage testing of
  213. XEmacs packages.
  214. X@item
  215. XAnnotation Subsystem -- a set of functions to provide support for creating,
  216. Xusing and displaying information about Emacs Lisp code.
  217. X@item
  218. XEquality Subsystem -- a set of functions used by the testing
  219. Xsubsystems that provide different interpretations of equality.
  220. X@end itemize
  221. X
  222. XThe following sections explain the use of these functions to support
  223. Xthe steps in the testing process:
  224. X@itemize @bullet
  225. X@item
  226. XGetting Started
  227. X@item
  228. XInstrumenting a package
  229. X@item
  230. XTesting a Package
  231. X@item
  232. XAnalyzing Test Results
  233. X@item
  234. XDisplaying Test Results
  235. X@end itemize
  236. X
  237. XThe system is designed to test Emacs-Lisp programs, and is implemented as a
  238. Xminor mode of Emacs-Lisp mode (See Section 28.1 [Minor Modes] of the GNU
  239. XEmacs Reference Manual).
  240. X
  241. X@node starting, testing, introduction, top
  242. X@chapter Getting Started
  243. X
  244. XThis section describes how to begin using the Test package to test
  245. XEmacs packages.
  246. X
  247. X@section Loading and Initialization
  248. X
  249. XTo start testing you probably want a fresh Emacs session with no extraneous
  250. Xbuffers or processes hanging around.  Non-essential extras will just slow
  251. Xdown the state capture and achieve functions.  If you have a busy
  252. X@file{.emacs} file you may want to keep a trimmed back copy just for test
  253. Xsessions.
  254. X
  255. XOnce in Emacs visit the file containing Emacs-lisp code to be tested,
  256. Xthen enter:
  257. X@example
  258. XM-x load-file
  259. Xtest.el
  260. XM-x test-mode
  261. X@end example
  262. XThe mode line at the bottom of your window should show ``(Emacs-lisp
  263. XTest)'' in the mode field.  You are now in Test mode.
  264. X
  265. XProbably the first thing to do at this point is to use @samp{C-c n} to
  266. Xgenerate a new buffer containing a test script template.  This is a good
  267. Xstarting point for creating a new test script; the template is shown in
  268. Xsection 2.3 of this document.  The task now confronting you is to develop a
  269. Xtest suite that will exercise your package throughly, not only to test it
  270. Xnow but also to have an automated regression test.  The remainder of this
  271. Xdocument will guide you through this task.
  272. X
  273. XFigure 2 illustrates the overall flow of data in the Test system.
  274. X
  275. X@group
  276. X@example
  277. X        +-------------+
  278. X        |Source Text  |
  279. X        +-------------+
  280. X                       \
  281. X                        \
  282. X                         \
  283. X                          Instrument
  284. X                         /
  285. X                        /
  286. X                       /
  287. X        +-------------+                     +-------------+
  288. X        |Instrumented |                     | Test Cases  |
  289. X        |    Text     |                     +-------------+
  290. X        +-------------+                    /
  291. X                       \                  /
  292. X                        \                /
  293. X                         \              /
  294. X                          \            /
  295. X                              Execute
  296. X                                       \
  297. X                                        \
  298. X                                         \
  299. X                                          \
  300. X                                            +-------------+
  301. X                                            |Test Results |
  302. X                                            +-------------+
  303. X                                           /        ^
  304. X                                          /         |
  305. X                                         /          |
  306. X                                        /           v
  307. X                                 Display         Analyze
  308. X
  309. X
  310. X
  311. X@end example
  312. X@center Figure 2.  Test Data Flow
  313. X@end group
  314. X
  315. X@section Test Mode
  316. X
  317. XThe package `@samp{test.el}' provides several functions to the user:
  318. X@table @samp
  319. X@item C-c n
  320. XStart a new test script
  321. X@code{ (tst-new-script-buffer)}
  322. X@item C-c i
  323. X(Re-)instrument a test program buffer @code{ (tst-instrument)}.
  324. X@item C-c x
  325. XTest the program, using the test script @code{ (tst-execute)}.
  326. X@item C-c c
  327. XRecord a GNU Emacs state for later use
  328. X@code{ (tst-capture-state)}.
  329. X@item C-c a
  330. XAchieve a previously saved GNU Emacs state
  331. X@code{ (tst-achieve-state)}.
  332. X@item C-c C-a
  333. XAchieve a state previously saved-to-file
  334. X@code{ (tst-achieve-state-from-file)}.
  335. X@item C-c C-c
  336. XCapture current emacs state to file
  337. X@code{ (tst-capture-state-to-file)}.
  338. X@item C-c C-r
  339. XRead a previously saved-to-file state into a variable
  340. X@code{ (tst-read-state-from-file)}.
  341. X@item C-c C-w
  342. XWrite a state previously captured in a variable to a file
  343. X@code{ (tst-write-state-to-file)}.
  344. X@item C-c f
  345. XAnalyze (filter) the results of running the test(s) @code{ (tst-analyze)}.
  346. X@item C-c d
  347. XDisplay the annotations about the test @code{ (tst-display-mode)}.
  348. X@item C-c q
  349. XExit test mode @code{ (test-mode)}.
  350. X@end table
  351. X
  352. X@section Contents of the *test script* Buffer
  353. X
  354. X
  355. X@example
  356. X(defun test-script ()
  357. X  (interactive)
  358. X                    ; Local Variables
  359. X  (let (pre post actual)
  360. X                    ; Body
  361. X    (switch-to-buffer foo)
  362. X    (erase-buffer)
  363. X    (insert-file foo)
  364. X    (goto-char (point-min))
  365. X    (emacs-lisp-mode)
  366. X    (test-mode)
  367. X    (tst-instrument)
  368. X                    ; 1st test run
  369. X    (tst-read-state-from-file 'post expected-state-file1)
  370. X    (tst-achieve-state-from-file 'pre initial-state-file1)
  371. X    (foo args)
  372. X    (tst-capture-state 'actual nil nil)
  373. X;;; If you have a lot of tests, consider a while loop
  374. X  ) ; let
  375. X) ; defun
  376. X@end example
  377. X
  378. X@section The Example -- box.el
  379. X
  380. XThe package `@samp{box.el}' provides two functions to the user:
  381. X@code{box-region} and @code{unbox}.
  382. XThe first function encloses the current region with a box:
  383. X
  384. X@group
  385. X@example
  386. X/********************************************\
  387. X* A boxed region                             *
  388. X* may have lines of text of varying lengths. *
  389. X* A side effect of boxing is to normalize    *
  390. X* the length of lines.                       *
  391. X\********************************************/
  392. X@end example
  393. X@end group
  394. X
  395. XThe second function undoes the effect of the first by removing any boxes
  396. Xwithin the region.  This simple package will be used in this document as an
  397. Xexample of a package to be tested using the Test package.
  398. X
  399. X@node testing, instrumenting, starting, top
  400. X@chapter Testing Your Package
  401. X
  402. XAs mentioned at the beginning of this document, Emacs packages are
  403. Xgenerally state changing operations.  You invoke the package with a session
  404. Xthat is in some arbitrary @i{initial state}.  The package modifies
  405. Xselected aspects of this @i{initial state} in a defined manner and leaves
  406. Xthe session in some @i{final state}.  The @dfn{state} of a GNU Emacs
  407. Xsession consists of information on buffers, windows, processes, and other
  408. Xglobal information.  The components of the state that are used in the Test
  409. Xpackage are listed later in this section.
  410. X
  411. X@dfn{Regression Testing} is a technique for verifying that changes in a
  412. Xpackage do not unintentionally degrade the quality of the code.  Any
  413. Xchanges in one part of the package should not alter the functionality of
  414. Xother parts of the package.  State information plays two roles in
  415. Xregression testing of Emacs packages.  These are:
  416. X@enumerate
  417. X@item
  418. Xinitiating the run of a package in a consistent and
  419. Xpre-determined @dfn{initial state}, and
  420. X@item
  421. Xcomparing the @dfn{actual final state} after the completion of a
  422. Xpackage to a @dfn{desired final state}.
  423. X@end enumerate
  424. XThe regression testing components of @samp{test.el} allow you to
  425. X@dfn{capture} session states for later use, @dfn{achieve} these states to
  426. Xset up a test run, and test the @dfn{equality} of states for package
  427. Xverification.
  428. X
  429. XThe following example demonstrates these steps for regressions testing an
  430. Xarbitrary package.  Assume that a working version of some package exists.
  431. XNow suppose you wish to add some new function that requires some
  432. Xmodifications in the original code. After adding the new function you need
  433. Xto verify that the original functionality of the package has not changed.
  434. XIn other words, you need to verify that the code has not @dfn{regressed}
  435. Xfrom its original functionality.  To perform this testing, you
  436. X@dfn{capture} the initial state of a session, run the original package, and
  437. X@dfn{capture} the final state.  Following this, you @dfn{achieve} the
  438. Xinitial state that you previously captured, run the new version of the
  439. Xpackage, and perform an @dfn{equality} test to compare the new final state
  440. Xto the one that was captured after the run of the original package.  The
  441. Xstates should be equivalent if the test is successful.
  442. X
  443. XTwo extensions to this state comparison paradigm are:
  444. X@enumerate
  445. X@item
  446. XTesting for partial equivalence - Each Emacs package is supposed to change
  447. Xcertain aspects of a session state, but leave others unchanged.  For
  448. Xexample, a package may change the text of the current buffer but should
  449. Xleave the window configuration of the session intact.  Partial equivalence
  450. Xtesting consists of the following steps:
  451. X@enumerate
  452. X@item
  453. XCapture the initial state.
  454. X@item
  455. XRun the function to be tested.
  456. X@item
  457. XCompare the final state to the initial state.  The states should be
  458. Xequivalent in all areas except those that the test function is supposed to
  459. Xchange.
  460. X@end enumerate
  461. X@item
  462. XTesting functions that undo the effects of other functions - Some emacs
  463. Xpackages have a function that perform some state change and a corresponding
  464. Xfunction that undoes that change.  Testing these types of packages consists
  465. Xof the following steps:
  466. X@enumerate
  467. X@item
  468. XCapture the initial state.
  469. X@item
  470. XRun the function that performs the state change.
  471. X@item
  472. XRun the function that undoes the state change.
  473. X@item
  474. XCompare the final state to the initial state.  They should be equivalent.
  475. X@end enumerate
  476. X@end enumerate
  477. XThe remainder of this section describes the elements of the Test
  478. Xpackage that implement these aspects of regression testing.
  479. XIn summary, these are:
  480. X@itemize @bullet
  481. X@item
  482. X@code{capture} - saves the current state of the Emacs session
  483. Xin either a bound variable or UNIX file.
  484. X@item
  485. X@code{partial capture} - save part of the current state of the
  486. XEmacs session.  Some or all global variables may be excluded, and a subset
  487. Xof buffers may be selected.
  488. X@item
  489. X@code{achieve} - sets the state of the current session to one
  490. Xthat is either in a bound variable or a UNIX file.
  491. X@item
  492. X@code{equality} - compares two emacs sessions states for
  493. Xequivalence.
  494. X@item
  495. X@code{partial equality} - compares selected aspects of two emacs
  496. Xsession states for equivalence.
  497. X@item
  498. X@code{inequality} - using user defined hooks, compares two
  499. Xsession states within certain degrees of inequality (e.g. compares buffer
  500. Xcontents ignoring whitespace).
  501. X@end itemize
  502. X
  503. X@section Capturing and Achieving Emacs States
  504. X
  505. X@subsection GNU Emacs State Definition
  506. X
  507. XThe @dfn{capture} and @dfn{achieve} functions of @samp{test.el} represent
  508. Xan Emacs state as the hierarchy of data shown below.
  509. X@itemize @bullet
  510. X@item
  511. X@code{Global Bound Symbols} - Most of the information about an
  512. XEmacs session is contained in the values of symbols global to the session.
  513. XIn conventional programming language terms, this session information can be
  514. Xviewed as the values of global variables.  Some examples of common global
  515. Xbound symbols are:
  516. X@itemize @bullet
  517. X@item
  518. X@samp{global-abbrev-table} - the list of abbreviations global to
  519. Xthe session and their meanings.
  520. X@item
  521. X@samp{global-map} - a vector describing the mappings of all keys
  522. Xto Emacs commands.
  523. X@item
  524. X@samp{debug-on-error} - a flag that indicates that the Emacs
  525. Xdebugger should be called on an error (if non-nil).
  526. X@end itemize
  527. X@item
  528. X@code{Buffer Information} - Each Emacs session contains one or
  529. Xmore buffers.  The capture functions store the following information for
  530. Xeach active buffer:
  531. X@itemize @bullet
  532. X@item
  533. Xbuffer name - a unique name that identifies the buffer.
  534. X@item
  535. Xfile name - if the buffer is associated with a UNIX file, the
  536. Xname of that file.
  537. X@item
  538. Xpoint - the value of the cursor point in the buffer.
  539. X@item
  540. Xmark - the  value of the buffer's mark.
  541. X@item
  542. Xcontents - the contents of the buffer represented as a text string.
  543. X@item
  544. Xmodified - a flag indicating if the buffer has been modified
  545. Xsince last saved.
  546. X@item
  547. Xlocal map - the local key map for this buffer.
  548. X@item
  549. Xlocal bound symbols - symbols (variables) that are local to this
  550. Xbuffer (e.g., the @samp{current-mode} of the buffer).
  551. X@end itemize
  552. X@item
  553. X@code{Window Information} - At any time an Emacs session has
  554. Xone or more windows visible.  The capture functions store the following
  555. Xinformation for each window:
  556. X@itemize @bullet
  557. X@item
  558. Xedges - the upper left and lower right corner of the window in
  559. Xscreen coordinates.
  560. X@item
  561. Xbuffer - the buffer occupying this window.
  562. X@item
  563. Xstart - the integer position in the buffer where display starts
  564. Xin the respective window.
  565. X@item
  566. Xpoint - the integer position in the buffer where the point for
  567. Xthis window sits.
  568. X@item
  569. Xcurrent flag - a flag that is non-nil if this is the window in
  570. Xwhich the screen cursor currently is located.
  571. X@end itemize
  572. X@item
  573. X@code{Process Information} - An Emacs session may have invoked
  574. Xseveral UNIX processes during its lifetime.  These processes may have
  575. Xcompleted or may still be running.  Two common processes that run during an
  576. XEmacs sessions are the @samp{shell} and the process that displays the time,
  577. Xdate and system load on the @dfn{mode line}.  The @samp{Test} capture
  578. Xfunctions store the follow information for each process:
  579. X@itemize @bullet
  580. X@item
  581. Xbuffer - the name of the buffer to which the process is attached
  582. X(nil if the process is not related to a buffer, e.g., the display time
  583. Xprocess). 
  584. X@item
  585. Xprocess mark - the marker for the end of the last output from
  586. Xthe process.
  587. X@item
  588. Xcommand - the UNIX command that invoked the process.
  589. X@item
  590. Xexit status - if the process has completed, the UNIX return code
  591. Xfrom that process.
  592. X@item
  593. Xfilter - the name of an Emacs lisp function that receives all
  594. Xoutput of the process.
  595. X@item
  596. Xname - a unique name of the program invoked in the process.
  597. X@item
  598. Xsentinel - the name of an Emacs lisp function that is called
  599. Xwhen the process changes state (e.g. completes).
  600. X@item
  601. Xstatus - indicates whether the process is running, complete,
  602. Xetc.
  603. X@end itemize
  604. X@end itemize
  605. X
  606. XA significant item that is excluded from this state information is the
  607. Xcurrent definition of bound functions.  Recall that an Emacs user can
  608. Xdefine any new function with a @samp{defun} and load that function.
  609. XFurthermore, the user can redefine any existing function (e.g.
  610. X@code{forward-char} !) in this manner.  Saving the current definition of
  611. Xall bound functions would result in a huge state vector, and is therefore
  612. Xnot done.
  613. X
  614. X@subsection Capturing an Emacs Session State
  615. XWhen regression testing an Emacs package, you will mainly use the state
  616. Xcapture functions of Test in two ways:
  617. X@enumerate
  618. X@item
  619. Xto save a known @dfn{initial state} to use as the base state for
  620. Xa run of an Emacs package, and
  621. X@item
  622. Xto save a @dfn{final state} to later compare to the state of the
  623. Xsession after the run of a modified package.
  624. X@end enumerate
  625. X
  626. X@subsubsection Commands for Capturing State
  627. X
  628. X@table @samp
  629. X@item tst-capture-state-to-file
  630. XWrites the current state of the Emacs session to a file.  You are prompted
  631. Xfor the name of the file, the @dfn{exclude-variables} and the
  632. X@dfn{buffer-list}.  Refer to the @code{Usage Notes} below for details on
  633. Xthese last two items.  If the file you specify already exists it is
  634. Xoverwritten.
  635. X@item tst-write-state-to-file
  636. XWrites a state that is saved in a bound variable to a file.  You are
  637. Xprompted for the state variable name (which was created with
  638. X@samp{tst-capture-state}) and the name of the file.  If the file already
  639. Xexists it is overwritten.
  640. X@item tst-capture-state
  641. XSaves the state of the Emacs session in a state variable.  You are prompted
  642. Xfor the name of the file, the @dfn{exclude-variables} and the
  643. X@dfn{buffer-list}.  Refer to the @code{Usage Notes} below for more details
  644. Xon these last two items.  If the bound variable you specify already exists,
  645. Xit is overwritten.
  646. X@end table
  647. X
  648. X@subsubsection Usage Notes
  649. X
  650. XThe amount of information saved by @samp{tst-capture-state-to-file} and
  651. X@samp{tst-capture-state} is controlled by your responses to the command
  652. Xprompts.  These are:
  653. X@table @samp
  654. X@item List of buffers to capture:
  655. XThere are three possible responses to this prompt:
  656. X@enumerate
  657. X@item 
  658. X@samp{nil} to indicate that state information on all buffers should be
  659. Xsaved (the default).
  660. X@item
  661. XA list of of buffer names indicating for which buffers state information
  662. Xshould be saved.  For example, to save only the states of buffers
  663. X@samp{bar} and @samp{foo} you enter:
  664. X@example
  665. X       ("bar" "foo")
  666. X@end example
  667. X@item
  668. XA singleton list that is the name of a non-existent buffer if you do not
  669. Xwish to save any buffer state information.  For example, if no buffer
  670. X@samp{xxx} exists you could enter
  671. X@example
  672. X       ("xxx")
  673. X@end example
  674. Xto specify that capture not save any buffer state information.
  675. X@end enumerate
  676. X@item List global vars to exclude:
  677. XThere are three possible responses to this prompt:
  678. X@enumerate
  679. X@item
  680. X@samp{nil} to capture all global variables.
  681. X@item
  682. X@samp{all} to exclude all global variables from the captured
  683. Xstate.
  684. X@item
  685. XA list of global variable names to exclude from the captured state.  For
  686. Xexample, if you enter
  687. X@example
  688. X        ("obarray" "values")
  689. X@end example
  690. Xthe two global variables, @samp{obarray} and @samp{values}, are not
  691. Xcaptured.  This value is the default for the prompt since these two
  692. Xvariables have very large values that are rarely of use in testing.
  693. X@end enumerate
  694. X@end table
  695. X
  696. X@subsection Achieving an Emacs State
  697. X
  698. XWhen using Test you will mainly use the achieve state functions to return
  699. Xyour session to a known @dfn{initial state}.  With these functions you can
  700. Xmake repeated test runs by simply achieving the @dfn{initial state} between
  701. Xeach run.
  702. X
  703. X@subsubsection Commands for State Achieve
  704. X@table @samp
  705. X@item tst-read-state-from-file
  706. XReads a session state from a file into a bound symbol.  You are prompted
  707. Xfor the name of the file and the name of the bound symbol.  The file should
  708. Xhave been created by @samp{capture-state-to-file} or
  709. X@samp{write-state-to-file}.  If the bound symbol already exists, it will be
  710. Xoverwritten.
  711. X@item tst-achieve-state-from-file
  712. XSets the state of the emacs session to that saved in a file.  You are
  713. Xprompted for the name of the file.  The file should have been created by
  714. X@samp{capture-state-to-file} or @samp{write-state-to-file}.
  715. X@item tst-achieve-state
  716. XSets the state of the emacs session to that saved in a bound symbol.  You
  717. Xare prompted for the name of the bound symbol.  The symbol must have been
  718. Xcreated by @samp{tst-capture-state}.
  719. X@end table
  720. X
  721. X@subsubsection Usage Notes
  722. X
  723. XAchieving the state of a previous Emacs session is a non-trivial task that
  724. Xcan have many unexpected side-effects.  These are listed below:
  725. X@enumerate
  726. X@item
  727. XIf you want @samp{achieve} to preserve all existing buffers that were not
  728. Xpart of the state you are achieving, you may set the variable
  729. X@samp{tst-achieve-buffers-nondestructively} non nil.
  730. X@item
  731. XAchieving a previous state completely resets your Emacs session.  Any
  732. Xinformation in your current state will be overwritten by the achieved
  733. Xstate.  For example, any changes in buffers will not exist after the
  734. Xachieve process.  You should, therefore, make sure that you save any
  735. Xchanges to disk before running achieve.
  736. X@item
  737. XIf you are not careful you may find that previous versions of disk files
  738. Xoverwrite current changed versions.  The following scenario demonstrates
  739. Xthis problem.
  740. X@enumerate
  741. X@item
  742. XSuppose you have a file @samp{mytest} that is in a buffer of an emacs
  743. Xsession at the time you run @code{tst-capture-state-to-file}.
  744. X@item
  745. XNow suppose you make changes to this file over a period of a few days, and
  746. Xthen run @code{tst-achieve-state-from-file}.
  747. X@item
  748. XYour emacs session will now contain the old version of the file.
  749. X@item
  750. XIf written to disk, this old version will overwrite the current version of
  751. X@samp{mytest}.
  752. X@end enumerate
  753. X
  754. XYou can avoid this problem by testing packages only on dummy test files, or
  755. Xusing a special test directory with copies of files that are permanently
  756. Xstored in other directories, or by not capturing buffer @samp{mytest} and
  757. Xsetting @code{tst-achieve-buffers-nondestructively} to @code{t}.
  758. X
  759. X@item
  760. XThe state of an emacs session is partially dependent on the state of your
  761. Xentire UNIX session.  Therefore, the achieve state functions may not be
  762. Xable to restore your state to the exact one that was captured.  For
  763. Xexample, a process can not be started if the run image for the program no
  764. Xlonger exists on disk.  When testing and comparing states, it is best to
  765. Xrely only on the more common aspects of an Emacs session (e.g. buffers,
  766. Xwindows).
  767. X@item
  768. XAs explained earlier, the capture functions do not save all aspects of the
  769. Xsession.  A significant example is the current definition of all bound
  770. Xfunctions.  Therefore, the achieve functions will not restore these aspects
  771. Xof the session state.
  772. X@end enumerate
  773. X
  774. X@section Testing for equality
  775. X
  776. XThe equality package of @b{Test} compares two Emacs states for equivalence
  777. Xby invoking special equality functions on each of the data components
  778. Xcaptured in the state. Each of these equality functions compares only a
  779. Xsmall part of the entire state. The results of these comparisons are
  780. Xwritten into the buffer @samp{*equal-log*}. If two states are not equal
  781. Xthen you can determine where components differ by looking at this buffer.
  782. X
  783. XThe section @b{Equality Functions} provides a list of all of the
  784. Xequivalence testing functions.  The section @b{Partial Equality} explains
  785. Xhow you can accomplish testing a subset of a state. This is useful if you
  786. Xare only interested in differences between certain aspects of state, such
  787. Xas only the contents of buffers, but you do not care to hear about
  788. Xdifferences in other components, such as windows.  The section
  789. X@b{Inequality} explains how to add hooks to the equality functions. These
  790. Xhooks are called by the equality functions when two components are not
  791. Xequal but before a result is returned. A hook that you write can be
  792. Xinserted at this point and change a ``not equal'' result into an ``equal.''
  793. X
  794. X@subsection Equality Functions
  795. X
  796. XThe functions to compare states for equality are divided into two
  797. Xcategories.  One set of functions compares complete states, the second set
  798. Xof functions only uses the buffer components.
  799. X
  800. XThe following state equality functions are defined for interactive use.
  801. X@table @code
  802. X@item tst-equ-state
  803. XCompares two states for equality.  Each component in the first state is
  804. Xcompared to its corresponding component in the second state.
  805. X@item tst-equ-sessions
  806. XCompares the @b{sessions} component of two states.  The sessions components
  807. Xcontains all global variables.  These includes those that define key-maps
  808. Xand syntax tables.
  809. X@item tst-equ-buffers
  810. XCompares the @b{buffers} components of two states. Compares all of the
  811. Xbuffers in one state with those of a second state.
  812. X@item tst-equ-windows
  813. XCompares the @b{windows} components of two states.
  814. X@item tst-equ-process
  815. XCompares the @b{process} components of two states.
  816. X@end table
  817. X
  818. XThe following functions operate on just the @b{buffer} components of
  819. Xstates.  Objects of this type can be extracted from state objects by the
  820. Xfunction @code{tst-equ-find-buff-with-name}.
  821. X@table @code
  822. X@item tst-equ-buffer-state
  823. XCompares two buffers for equality. The following components are checked for
  824. Xequality: @b{point}, @b{mark}, @b{contents}, @b{modified}, @b{file},
  825. X@b{local-variables}.
  826. X@item tst-equ-point
  827. XCompares the @b{point} component of two buffers.
  828. X@item tst-equ-mark
  829. XCompares the @b{mark} component of two buffers.
  830. X@item tst-equ-file
  831. XCompares the @b{file} component of two buffers.
  832. X@item tst-equ-modified
  833. XCompares the @b{modified} component of two buffers.
  834. X@item tst-equ-contents
  835. XCompares the @b{contents} component of two buffers.  Contents are compared
  836. Xas two single strings.
  837. X@item tst-equ-contents-line
  838. XCompares the @b{contents} component of two buffers.  Contents are viewed as
  839. Xcomposed of lines of text, and compared line-by-line.
  840. X@item tst-equ-contents-region
  841. XCompares the @b{contents} component of two buffers. Only the contents
  842. Xwithin a region are compared. Region is delimited by point and mark.
  843. X@end table
  844. X
  845. X@subsection Partial Equality
  846. X
  847. XIf you are interested in only checking the equality of a subset of an Emacs
  848. Xstate, then there are four methods you can use.
  849. X
  850. X@table @code
  851. X@item tst-capture-state
  852. XYou can use this function to capture only a subset of state.  Once this has
  853. Xbeen done, equality testing will only be performed on those parts of the
  854. Xstate that where captured.
  855. X@item tst-equ-state-functions
  856. XThis variable contains a list of equality functions to be invoked when
  857. Xcomparing two states.  You can change it to test only those components of
  858. Xstate that interest you.  As an example, you might want to remove
  859. X@samp{tst-equ-windows} if you are not interested in differences in windows
  860. Xbetween states.
  861. X@item tst-equ-buff-state-functions
  862. XThis variable contains a list of equality functions to be invoked when
  863. Xcomparing two @dfn{buffer states}.  You can change it to test only those
  864. Xcomponents of @dfn{buffer state} that interest you.  As an example, you
  865. Xmight want to remove @samp{tst-equ-point} and @samp{tst-equ-mark} if you
  866. Xare not interested in those parts of the states.
  867. X@item tst-equ-find-buffer-with-name
  868. XUse this function to obtain only the part of state that is associated with
  869. Xa particular buffer.  You can then pass the result of this function to
  870. Xbuffer testing equality functions.
  871. X@end table
  872. X
  873. X@subsection Inequality
  874. X
  875. XSometimes the comparison of two objects yields ``not equal'' when wish to
  876. Xignore certain inequalities.  Each of the equality functions will execute a
  877. Xhook, if one is defined, and the comparison of the two objects yields ``not
  878. Xequal.''  Within the hook you can write your own test for equality and
  879. Xchange the result of the comparison if you so desire.
  880. X
  881. XFor each equality function, there exists a hook symbol that, when defined,
  882. Xwill be run if the two objects are not equal.  The name of the hook symbol
  883. Xcan be found by adding @samp{-hook} to the equality function name.  The
  884. Xvalue of this hook should then be set to the name of the hook function you
  885. Xwish to execute.  From within the the hook the two objects being compared
  886. Xcan be accessed by adding @samp{1} and @samp{2} to the equality function
  887. Xname.  The variable @code{tst-equ-result} should be set to @samp{t} or
  888. X@samp{nil} from within your hook.
  889. X
  890. XThe following example shows a hook, called @code{ignore-zero-points}, that
  891. Xis executed whenever the result of comparing the point components of two
  892. Xbuffers is not equal.  From within this function the two point components
  893. Xare accessed as @samp{tst-equ-point1} and @samp{tst-equ-point2}.  The hook
  894. Xchanges the result of a point comparison from @samp{nil} to @samp{t} if one
  895. Xof the points is at position zero.
  896. X
  897. X@example
  898. X
  899. X(setq tst-equ-point-hook 'ignore-zero-points)
  900. X
  901. X(defun ignore-zero-points ()
  902. X     "Equality point hook, changes result to t if one point    
  903. X      is at position zero."
  904. X
  905. X    (if (or (equal tst-equ-point1 0) (equal tst-equ-point2 0))
  906. X       (setq tst-equ-result t)  ; return t if one is zero
  907. X    ;else
  908. X       (setq tst-equ-result nil); otherwise return nil
  909. X        )
  910. X)
  911. X
  912. X@end example
  913. X
  914. XOf particular usefulness are the hooks that are associated with the
  915. Xcontents of two buffers. The equality function @samp{tst-equ-bs-contents}
  916. Xcompares the contents of two buffers by comparing strings that contain the
  917. Xentire contents of each buffer. Should this comparison fail it is sometimes
  918. Xuseful to compare the two strings after eliminating all white-space from
  919. Xeach string. The following hook, provided with this package, does such a
  920. Xcomparison.
  921. X
  922. X@example
  923. X
  924. X(setq tst-equ-contents-hook 'ignore-white-space)
  925. X
  926. Xdefun ignore-white-space()
  927. X   " Compares the contents of two buffers after removing all
  928. X     white-space from each."
  929. X
  930. X    (setq tst-equ-result (string-equal-less-regexp "\\s " 
  931. X        tst-equ-contents1 tst-equ-contents2))
  932. X)
  933. X@end example
  934. X
  935. XA second contents hook of interest is the one associated with the
  936. X@samp{tst-equ-contents-line function}. This function compares the contents
  937. Xof two functions on a line-by-line basis.  The hook for this function
  938. Xdiffers from all other hooks, in that it is called once per line, instead
  939. Xof once per call to its associated function. The two lines are accessed as
  940. X@samp{tst-equ-line1} and @samp{tst-equ-line2}.
  941. X
  942. X
  943. X@section Testing example
  944. X
  945. XThe example that follows illustrates how to write an emacs-lisp function
  946. Xthat uses the Test package to test another function you have written.  In
  947. Xthe example the two user supplied functions under test are:
  948. X@samp{box-region} and @samp{unbox}.
  949. X
  950. X@example
  951. X;;; test-box uses the Test package to test the functions box and unbox
  952. X;;; 
  953. X test-box ()
  954. X  (interactive)
  955. X                    ; Local Variables
  956. X  (let (initial-state                ; to hold states
  957. X         boxed-state
  958. X         final-state
  959. X         capture-buffer-list
  960. X    )
  961. X
  962. X    ; First create a buffer to use the functions on
  963. X    (get-buffer-create "box.junk")
  964. X    (set-buffer "box.junk")
  965. X    (erase-buffer)
  966. X    (insert-file "/project/gnutest/test/box.junk")
  967. X
  968. X    ; Save the initial state
  969. X    ; Since we're only concerned with one buffer include
  970. X    ;     include that in the capture list
  971. X    (setq capture-buffer-list '("box.junk"))
  972. X    (tst-capture-state 'initial-state capture-buffer-list nil)
  973. X
  974. X    ; execute the box function 
  975. X    (goto-char (point-min))
  976. X    (set-mark (point-max))
  977. X    (box-region nil)
  978. X
  979. X    ; capture the boxed state
  980. X    (tst-capture-state 'boxed-state capture-buffer-list nil)
  981. X
  982. X    ; unbox and capture again
  983. X    (unbox nil)
  984. X    (tst-capture-state 'final-state capture-buffer-list nil)
  985. X
  986. X    ; compare the initial state to the final state
  987. X    ; they should be exactly equal
  988. X    (if (tst-equ-state initial-state final-state
  989. X                       "Compare before box to after unbox")
  990. X    (message "Box/unbox test passed")
  991. X    (message "Box/unbox test failed"))
  992. X
  993. X    )                    ; let
  994. X  )                    ; defun
  995. X@end example
  996. X
  997. X@subsection Contents of *equal-log*
  998. X
  999. XEach of the equality functions writes the results of its comparison into a
  1000. Xbuffer named ``*equal-log*''.  If this buffer does not exist, then it is
  1001. Xcreated.  The contents of the buffer are never erased nor is the buffer
  1002. Xever deleted, these actions are left to the user.
  1003. X
  1004. XThe buffer is created in Outline Mode. This allows selective hiding of
  1005. Xcomparisons that are not of interest to the user.
  1006. X
  1007. XIf the result of a comparison is nil (i.e. not equal) then that entry in
  1008. Xthe log is flagged with a question mark (?).  In most cases, the two
  1009. Xdiffering objects are also logged as in the following example.
  1010. X
  1011. X@example
  1012. X*  ?State comparison: Compare before box to after unbox
  1013. X
  1014. X**    ?Sessions state
  1015. X***    ? Global symbols
  1016. X        data-bytes-free   5350948 5176868
  1017. X        this-command   nil kill-region
  1018. X        data-bytes-used   383452 557532
  1019. X        ?post not found in second state
  1020. X        post   nil nil
  1021. X        ?file not found in second state
  1022. X        file
  1023. X        statevar   state post
  1024. X
  1025. X
  1026. X**    ?Buffers state
  1027. X
  1028. X**    Comparison of buffers named: *scratch*
  1029. X***     point: "1" "1"
  1030. X***     mark: nil nil
  1031. X***     contents: contents equal
  1032. X***     modified: nil nil
  1033. X***     file: nil nil
  1034. X***     local-vars: local variables are equal 
  1035. X
  1036. X**    Comparison of buffers named:  *Minibuf-0*
  1037. X***     point: "1" "1"
  1038. X***     mark: nil nil
  1039. X***     contents: contents equal
  1040. X***     modified: nil nil
  1041. X***     file: nil nil
  1042. X***     local-vars: local variables are equal 
  1043. X
  1044. X**    Comparison of buffers named: box.el
  1045. X***     point: "1" "1"
  1046. X***     mark: 4480 4480
  1047. X***     contents: contents equal
  1048. X***     modified: t t
  1049. X***     file: nil nil
  1050. X***     local-vars: local variables are equal 
  1051. X
  1052. X**    Comparison of buffers named: box.el-instrumented
  1053. X***     point: "5608" "5608"
  1054. X***     mark: 5608 5608
  1055. X***     contents: contents equal
  1056. X***     modified: t t
  1057. X***     file: nil nil
  1058. X***     local-vars: local variables are equal 
  1059. X
  1060. X**    ?Comparison of buffers named: box.junk
  1061. X***     ?point: "1" "234"
  1062. X***     ?mark: 235 1
  1063. X***     ?contents: contents not equal
  1064. X***     modified: t t
  1065. X***     file: nil nil
  1066. X***     local-vars: local variables are equal 
  1067. X
  1068. X
  1069. X**    Processes state
  1070. X
  1071. X
  1072. X**    Window state
  1073. X
  1074. X***     window
  1075. X****         window-edges: (0 0 10 9) (0 0 10 9)
  1076. X****         window-buffer: "box.junk" "box.junk"
  1077. X****         window-start: 1 1
  1078. X****         window-point: 1 1
  1079. X****         current-window: t t
  1080. X
  1081. X
  1082. X@end example
  1083. X
  1084. X@node instrumenting, analyzing, testing, top
  1085. X@chapter Instrumenting a Package
  1086. X
  1087. XUse the @code{tst-instrument} command for instrumenting Lisp code.
  1088. XInstrumenting copies the contents of the current buffer to a new buffer
  1089. Xnamed for the current buffer concatenated with @samp{-instrumented}.  The
  1090. Xnew buffer is set to emacs-lisp-mode.  Instrumenting initializes the
  1091. Xannotation data base, adds the instrumentation to the copied code, and
  1092. Xfinally evaluates the entire copied buffer.
  1093. X
  1094. X@section Instrumentation Probes
  1095. X
  1096. XInstrumentation acts on certain lists that represent functions within a
  1097. X@code{defun} by adding an instrumentation probe.  Candidate lists are
  1098. Xidentified and Lisp code is added around the list.  A list representing a
  1099. Xfunction that has the form, @samp{(function arg1 arg2)}, after insertion of
  1100. Xthe instrumentation probe will have the form, @samp{(tst-cover #id
  1101. X(function arg1 arg2))}.  Instrumentation assigns the line number of the
  1102. Xfunction within the buffer as the #id.
  1103. X
  1104. X@section Cover Function
  1105. X
  1106. XThe instrumentation probe consists of the invocation of the function
  1107. X@code{tst-cover} with two arguments, a unique identifier and the function
  1108. Xthat was instrumented.  @code{Tst-cover} uses the identifier as a key into
  1109. Xthe annotation data base, stores the result of the instrumented function,
  1110. Xincrements an invocation counter, and returns the result of the
  1111. Xinstrumented function as its function value.
  1112. X
  1113. X
  1114. X@section Instrumentation Example
  1115. X
  1116. XOriginal Code:
  1117. X
  1118. X@example
  1119. X(defun factorial (n)
  1120. X  (let
  1121. X      (result)
  1122. X    (if
  1123. X        (< n 2)
  1124. X        (setq result 1)
  1125. X      (setq result
  1126. X         (* n
  1127. X            (factorial
  1128. X             (1- n)))))
  1129. X    result))
  1130. X@end example
  1131. X
  1132. XInstrumented Code:
  1133. X
  1134. X@example
  1135. X(defun factorial (n)
  1136. X  (tst-cover 2 (let
  1137. X      (result)
  1138. X    (tst-cover 4 (if
  1139. X        (tst-cover 5 (< n 2))
  1140. X        (tst-cover 6 (setq result 1))
  1141. X      (tst-cover 7 (setq result
  1142. X         (tst-cover 8 (* n
  1143. X            (tst-cover 9 (factorial
  1144. X             (tst-cover 10 (1- n))))))))))
  1145. X    result)))
  1146. X@end example
  1147. X
  1148. X@node analyzing, displaying, instrumenting, top
  1149. X@chapter Analyzing the Test Results
  1150. X
  1151. XThis section explains how to use the @code{analyze} function
  1152. X
  1153. X@section Analysis Functions
  1154. X
  1155. XThe Coverage Analysis package is designed to run after a series of tests
  1156. Xhas been performed using the instrumented version of the code under test.
  1157. XIt retrieves data from the annotation database and detects the following
  1158. Xtesting anomalies:
  1159. X
  1160. X@itemize @bullet
  1161. X@item
  1162. XFailure to execute an expression.
  1163. X@item
  1164. XFailure to produce more than one value for an expression.
  1165. X@end itemize
  1166. XWhen these conditions are detected additional attributes are stored in the
  1167. Xannotation database in a format suitable for extraction by the display
  1168. Xcomponent of Test.
  1169. X
  1170. XAnalysis is invoked by the command:
  1171. X
  1172. X@example
  1173. X    tst-analyze
  1174. X@end example
  1175. X
  1176. XIf an expression is not executed, the attribute ``zero'' is inserted with a
  1177. Xconstant value.  This constant value is defined by the following variable:
  1178. X@example
  1179. X    tst-anl-zero-counts
  1180. X@end example
  1181. XIf an expression returns a constant value, the attribute ``constant'' is
  1182. Xinserted with the value of the constant.  If an expression is only executed
  1183. Xonce, it is deemed to return a constant result.
  1184. X
  1185. XYou can re-run the analysis function without re-instrumenting the code
  1186. Xunder test.  If, for example, an initial set of tests indicates a number of
  1187. Xunexecuted expressions, you can run additional tests and analyze the
  1188. Xcombined results without re-running the complete set of tests.  Note
  1189. Xhowever, that if you re-instrument the code, the annotation database is
  1190. Xreinitialized and the results of previous tests, including any analysis
  1191. Xresults will be lost (unless you explicitly save the annotation database
  1192. Xusing tst-ann-get-db).
  1193. X
  1194. X@section Sample Analysis Results
  1195. X
  1196. XNormally you would view the results of an analysis using the display
  1197. Xpackage on-line.  However, the following indicates the information produced
  1198. Xby the analysis.
  1199. X
  1200. X@example
  1201. X# Test analysis of box.el
  1202. X#   (lines which were never evaluated during tests, indicated by 
  1203. X#    the string ``NEVER->>'',  or which returned the same value
  1204. X#    every time they were evaluated, including the value.)
  1205. X
  1206. Xbox.el:31== nil 
  1207. Xbox.el:33== nil 
  1208. Xbox.el:34== nil 
  1209. Xbox.el:35== nil 
  1210. Xbox.el:37== 1
  1211. Xbox.el:38== 0 
  1212. Xbox.el:39== nil 
  1213. Xbox.el:41== nil 
  1214. Xbox.el:42== nil 
  1215. Xbox.el:49== 1
  1216. Xbox.el:50== nil
  1217. X
  1218. X...
  1219. X
  1220. Xbox.el:94== nil 
  1221. Xbox.el:95== nil 
  1222. Xbox.el:109== #<marker at 1 in box.junk>
  1223. Xbox.el:115== nil 
  1224. Xbox.el:116== t 
  1225. Xbox.el:121== NEVER->> 
  1226. Xbox.el:122== NEVER->>
  1227. Xbox.el:128== nil 
  1228. Xbox.el:129== nil 
  1229. Xbox.el:134== NEVER->> 
  1230. Xbox.el:135== NEVER->>
  1231. Xbox.el:140== nil 
  1232. X
  1233. X...
  1234. X
  1235. X@end example
  1236. X
  1237. X@node displaying, running, analyzing, top
  1238. X@chapter Displaying Test Results
  1239. X
  1240. XThe @dfn{coverage} component of the Test package is useful for measuring
  1241. Xhow thoroughly a test script exercises an emacs-lisp package.  The
  1242. Xinteractive Test display mode lets you browse the annotated code.  The
  1243. Xbatch display function creates a summary report which may be browsed later
  1244. Xusing the Emacs ``compilation'' mode.
  1245. X
  1246. X@section Display Mode---creating annotation windows
  1247. X
  1248. XEvaluating an instrumented buffer of emacs-lisp code creates a database of
  1249. X@dfn{annotations} for each instrumented line.  The two data stored during
  1250. Xevaluation are: @samp{count}, the number of times each line has been
  1251. Xevaluated, and @samp{values}, a list of the resultant values.  Analyzing
  1252. Xthe database adds two new annotations to various lines in the database:
  1253. X@samp{zero}, the line was never evaluated, and @samp{constant}, the value
  1254. Xreturned was the same every time it was evaluated.  Note that a line
  1255. Xevaluated exactly once will be flagged as having a constant value.
  1256. X
  1257. XDisplay mode puts up these @dfn{annotations} beside the lisp code in one or
  1258. Xmore @dfn{annotation windows} which are linked to the @dfn{lisp window} so
  1259. Xthat all windows scroll together.  The functions available for creating
  1260. Xannotation windows are as follows:
  1261. X
  1262. X@table @samp
  1263. X@item C-c c
  1264. XOpen an annotation window which highlights code which returned the
  1265. Xsame value during testing (@samp{tst-display-constant}).
  1266. X
  1267. X@item C-c z
  1268. XOpen an annotation window which highlights code which was never
  1269. Xevaluated during testing (@samp{tst-display-zero}).
  1270. X
  1271. X@item M-x tst-display-open-buffer
  1272. XCreate a buffer containing the database values for a particular attribute
  1273. Xover all lines of the lisp buffer.  Valid attributes are @samp{count}, the
  1274. Xcount of how many times that line was evaluated, and @samp{values}, a list
  1275. Xwith each element the result of one evaluation of that line.
  1276. X
  1277. X@item M-x tst-display-open-window
  1278. XOpen an annotation window onto a buffer created by a prior evaluation
  1279. Xof @samp{tst-display-open-buffer}.
  1280. X
  1281. X@item C-c C-h
  1282. XOpen a help window showing the key bindings for display mode 
  1283. X(@samp{tst-display-mode-help}).
  1284. X
  1285. X@item C-c q
  1286. XExit display mode (@samp{tst-display-mode-exit}).
  1287. X@end table
  1288. X
  1289. XTypically the first thing you will do after entering display mode is to
  1290. Xtype @samp{C-c c C-c z} to create two annotation windows which point out
  1291. Xany lines in the lisp buffer which either were never evaluated or always
  1292. Xreturned the same value.  In the first case you probably need to add to
  1293. Xyour test script to either call an unreferenced function or exercise the
  1294. Xother side of a conditional expression.  The second case may require some
  1295. Xinvestigation.  One possibility is that the line is something like:
  1296. X@example
  1297. X(setq very-important-variable nil).
  1298. X@end example
  1299. XThis expression, of course, always returns the same value.  Another
  1300. Xpossibility is that the line was only evaluated once, in which case you
  1301. Xmight want to add to your test script to hit it again.  The third
  1302. Xpossibility is that you overlooked a parameter when composing your test
  1303. Xscript.
  1304. X
  1305. XIf you want to look at the other annotations in the database, you may do so
  1306. Xwith the commands @samp{M-x tst-display-open-buffer} and @samp{M-x
  1307. Xtst-display-open-window}.  You must use them in that order, and each one
  1308. Xwill prompt for an ``attribute name'' which may be either of @samp{count}
  1309. Xor @samp{values}.
  1310. X
  1311. X@section Display Mode---moving within annotation windows
  1312. X
  1313. XThe annotation windows are kept in step with the lisp window through
  1314. Xseveral functions which take the place of the usual cursor movement
  1315. Xcommands while in display mode.  These are described below:
  1316. X
  1317. X@table @samp
  1318. X@item C-n
  1319. XMove down one line vertically in the lisp window and all associated
  1320. Xannotation windows.  On reaching the bottom of the window, scroll windows
  1321. Xtogether (@samp{tst-display-next-line}).
  1322. X        
  1323. X@item C-p
  1324. XMove up one line vertically in the lisp window and all associated
  1325. Xannotation windows.  On reaching the top of the window, scroll windows
  1326. Xtogether (@samp{tst-display-previous-line}).
  1327. X    
  1328. X@item C-v
  1329. XScroll forward in the lisp window and any associated annotation windows
  1330. Xkeeping them aligned (@samp{tst-display-scroll-up}).
  1331. X        
  1332. X@item M-v
  1333. XScroll backward in the lisp window and any associated annotation windows
  1334. Xkeeping them aligned (@samp{tst-display-scroll-down}).
  1335. X
  1336. X@item C-c l
  1337. XClear screen and redisplay, scrolling the lisp window and any associated
  1338. Xannotation windows together to center the line containing point
  1339. X(@samp{tst-display-redraw}).
  1340. X
  1341. X@end table
  1342. X
  1343. XThe usual cursor up and down keys are @samp{C-n} and @samp{C-p},
  1344. Xrespectively.  In display mode these move point in all annotation windows
  1345. Xsimultaneously so that when the limits of the screen are reached all
  1346. Xwindows will scroll together.  Similarly the scroll-up and scroll-down keys
  1347. X@samp{C-v} and @samp{M-v} are rebound in display mode to functions which
  1348. Xkeep track of what annotation windows are open and scroll them in step with
  1349. Xthe lisp buffer.  It is still possible for the windows to get out of step
  1350. X(e.g. after using @samp{M-<}), so the @samp{C-c l} key will resynchronize
  1351. Xall annotation windows while recentering the line containing point just as
  1352. Xthe @samp{C-l} key does for a single window.
  1353. X
  1354. X@section Batch Display of Analysis
  1355. X
  1356. XQuite separate from the display mode is a display function that is designed
  1357. Xto give a concise summary of test coverage without your interaction.  This
  1358. Xfunction can be run in batch or interactively.  (It was originally intended
  1359. Xfor only batch operation, hence the name.)
  1360. X
  1361. X@table @samp
  1362. X@item M-x tst-display-batch
  1363. XGenerate a @dfn{compilation style} buffer containing @dfn{zero} and
  1364. X@dfn{constant} analyses from the database.
  1365. X@end table
  1366. X
  1367. XYou need not be in display mode to use @samp{tst-display-batch}.  You are
  1368. Xmost likely to use it in a test script run from batch mode to dump out a
  1369. Xsummary of test coverage at the end of a run.  However it is also useful
  1370. Xfrom interactive mode because it takes advantage of the Emacs function
  1371. X@samp{C-x`} (@samp{next-error}), often used to view compiler error
  1372. Xmessages.  The first invocation of @samp{C-x`} parses the error messages in
  1373. Xthe buffer named @samp{*compilation*} then places point in one window on
  1374. Xthe line of code referenced by the error message shown at the top of the
  1375. Xother window.  Successive @samp{C-x`} keystrokes advance to successive
  1376. Xerror messages and the corresponding lines in the code buffer.
  1377. X
  1378. XThe @samp{M-x tst-display-batch} command writes into the
  1379. X@samp{*compilation*} buffer a line for every line in the lisp buffer that
  1380. Xhas either a @samp{zero} or @samp{constant} annotation.  Subsequent uses of
  1381. X@samp{C-x`} advance to the next error and the corresponding line in the
  1382. Xlisp buffer.
  1383. X
  1384. X@section The Example
  1385. X
  1386. XThe following is the output of the evaluation of @samp{tst-display-batch}
  1387. Xin our example test script.  Notice that some deficiencies in the test
  1388. Xscript are pointed out: error conditions were not exercised (see lines
  1389. X121-122 and 134-135 in Appendix A); and not enough different input texts
  1390. Xwere ``boxed'' to really stress the package under test (e.g. line 40, input
  1391. Xtext always same width).
  1392. X
  1393. X@example
  1394. X# Test analysis of box.el
  1395. X#   (lines which were never evaluated during tests or returned
  1396. X#    the same value every time they were evaluated.)
  1397. Xbox.el:31==  nil
  1398. Xbox.el:33==  nil
  1399. Xbox.el:34==  nil
  1400. Xbox.el:35==  nil
  1401. Xbox.el:37==  1
  1402. Xbox.el:38==  0
  1403. Xbox.el:39==  nil
  1404. Xbox.el:40==  41
  1405. Xbox.el:41==  nil
  1406. Xbox.el:42==  nil
  1407. Xbox.el:43==  42
  1408. Xbox.el:47==  44
  1409. Xbox.el:49==  1
  1410. Xbox.el:50==  nil
  1411. Xbox.el:51==  nil
  1412. Xbox.el:52==  nil
  1413. Xbox.el:53==  nil
  1414. Xbox.el:55==  nil
  1415. Xbox.el:56==  nil
  1416. Xbox.el:57==  nil
  1417. Xbox.el:58==  nil
  1418. Xbox.el:59==  nil
  1419. Xbox.el:62==  nil
  1420. Xbox.el:63==  nil
  1421. Xbox.el:64==  nil
  1422. Xbox.el:65==  nil
  1423. Xbox.el:67==  nil
  1424. Xbox.el:68==  nil
  1425. Xbox.el:69==  1
  1426. Xbox.el:70==  12
  1427. Xbox.el:71==  nil
  1428. Xbox.el:72==  nil
  1429. Xbox.el:73==  nil
  1430. Xbox.el:74==  12
  1431. Xbox.el:75==  nil
  1432. Xbox.el:80==  nil
  1433. Xbox.el:91==  nil
  1434. Xbox.el:93==  nil
  1435. Xbox.el:94==  nil
  1436. Xbox.el:95==  nil
  1437. Xbox.el:109==  #<marker at 6 in box.junk>
  1438. Xbox.el:115==  nil
  1439. Xbox.el:116==  t
  1440. Xbox.el:121==  NEVER->>
  1441. Xbox.el:122==  NEVER->>
  1442. Xbox.el:128==  nil
  1443. Xbox.el:129==  nil
  1444. Xbox.el:134==  NEVER->>
  1445. Xbox.el:135==  NEVER->>
  1446. Xbox.el:140==  nil
  1447. Xbox.el:141==  nil
  1448. Xbox.el:143==  nil
  1449. Xbox.el:144==  t
  1450. Xbox.el:145==  NEVER->>
  1451. Xbox.el:147==  t
  1452. Xbox.el:149==  nil
  1453. Xbox.el:150==  nil
  1454. Xbox.el:151==  nil
  1455. Xbox.el:153==  nil
  1456. Xbox.el:154==  nil
  1457. Xbox.el:157==  nil
  1458. Xbox.el:159==  nil
  1459. Xbox.el:160==  #<marker at 6 in box.junk>
  1460. X
  1461. X@end example
  1462. X
  1463. X@node running, epilogue, displaying, top
  1464. X@chapter Running Test in Batch Mode
  1465. X
  1466. X@section Preparation
  1467. X
  1468. XBefore running a set of tests, you must prepare the following items:
  1469. X@itemize @bullet
  1470. X@item
  1471. XA package to test.
  1472. X@item
  1473. XA test script, usually written as a single function.
  1474. X@item
  1475. XA set of precondition states---one for each test (although many
  1476. Xtests may share the same precondition).
  1477. X@item
  1478. XA set of expected postcondition states---one for each test (some
  1479. Xsharing is possible).
  1480. X@end itemize
  1481. XTest scripts are discussed in the next section.
  1482. X
  1483. XYou will probably want to use the state-capturing functions (e.g.,
  1484. X``tst-capture-state'', ``tst-write-state-to-file'') to prepare and save
  1485. Xstates in files.  In doing this, strive for minimality of states.  That is,
  1486. Xavoid complicating the states with extra components, particularly buffers
  1487. Xand windows, that do not contribute to the functionality being tested.
  1488. XThis will make it easier to read and comprehend the testing states, and
  1489. Xwill result in more efficient test scripts.  (The instrumentation and
  1490. Xanalysis components of Test are designed to assist you in discovering the
  1491. Xinadequacies of your test scripts.  It is best to start with too little
  1492. Xtesting, and add additional tests as the analysis dictates.)
  1493. X
  1494. XBelow is an example scenario for preparing the states used in a testing
  1495. Xscript discussed later.  Note that the functions would be invoked
  1496. Xinteractively, even though they are shown in ``program invocation'' style.
  1497. X@example
  1498. X(load "test.el")
  1499. X(load "box.el")
  1500. X(find-file "sample")
  1501. X... go to an appropriate location ...
  1502. X(set-mark)
  1503. X... go to an appropriate location ...
  1504. X(tst-capture-state-to-file "pre-box")
  1505. X(box-region)
  1506. X(tst-capture-state-to-file "exp-box-1")
  1507. X(unbox)
  1508. X(tst-capture-state-to-file "exp-unbox-1")
  1509. X(box-region t)
  1510. X(tst-capture-state-to-file "exp-box-2")
  1511. X(unbox t)
  1512. X(tst-capture-state-to-file "exp-unbox-2")
  1513. X@end example
  1514. XNote that in this scenario the expected result of applying a function is
  1515. Xcreated by applying the function to the precondition state.  It is hard to
  1516. Ximagine how the test could fail, but it might for unexpected reasons.  A
  1517. Xbetter method of creating the test states is to use an independent method,
  1518. Xsuch as repeated application of simpler functions (e.g., ``insert'',
  1519. X``next-line'').  Still, ``safe'' tests, such as that shown above, are
  1520. Xuseful for regression testing.
  1521. X
  1522. X@section Batch Test Scripts
  1523. X
  1524. XA test run usually consists of the following steps:
  1525. X@enumerate
  1526. X@item
  1527. XRead testing states from files.
  1528. X@item
  1529. XInitialize the testing environment:
  1530. X@enumerate
  1531. X@item
  1532. XFind the object package (the code to be tested).
  1533. X@item
  1534. XInstrument the package.
  1535. X@end enumerate
  1536. X@item
  1537. XRun each test:
  1538. X@enumerate
  1539. X@item
  1540. XAchieve the precondition state of the test.
  1541. X@item
  1542. XExecute the function to be tested.
  1543. X@item
  1544. XCapture the postcondition state.
  1545. X@item
  1546. XCompare the postcondition state to the expected postcondition state.
  1547. X@end enumerate
  1548. X@item
  1549. XSave the results of testing in a file.
  1550. X@item
  1551. XAnalyze the testing (filter the collected data) and save the results.
  1552. X@end enumerate
  1553. XNote that a set of tests may reuse testing states, especially the
  1554. Xpreconditions of tests.  That is why it is wise to read all of the needed
  1555. Xtesting states from files first.  Also, it is good style to minimize state
  1556. Xchanges during testing (except for the execution of tested functions, of
  1557. Xcourse), so that the test script may be modified without unforeseen side
  1558. Xeffects.
  1559. X
  1560. XBelow is an example test script for testing functions ``box-region'' and
  1561. X``unbox'' in package ``box.el''.  This script does not contain enough
  1562. Xtests, which the instrumentation should expose.
  1563. X
  1564. X@example
  1565. X(load "test.el")
  1566. X
  1567. X(defun script ()
  1568. X  (let (post-state pre-box exp-box-1 exp-box-2
  1569. X                   pre-unbox exp-unbox-1 exp-unbox-2)
  1570. X                                        ; Load states from files
  1571. X    (tst-read-state-from-file 'pre-box "pre-box")
  1572. X    (tst-read-state-from-file 'exp-box-1 "exp-box-1")
  1573. X    (tst-read-state-from-file 'exp-box-2 "exp-box-2")
  1574. X    (tst-read-state-from-file 'pre-unbox "pre-unbox")
  1575. X    (tst-read-state-from-file 'exp-unbox-1 "exp-unbox-1")
  1576. X    (tst-read-state-from-file 'exp-unbox-2 "exp-unbox-2")
  1577. X                                        ; Instrument package
  1578. X    (find-file "box.el")
  1579. X    (tst-instrument)
  1580. X                                        ; Initialize test environment
  1581. X    (find-file "sample")
  1582. X                                        ; Tests
  1583. X    ; TEST box-1
  1584. X    (tst-achieve-state pre-box)
  1585. X    (box-region nil)
  1586. X    (tst-capture-state 'post-state)
  1587. X    (tst-equ-state post-state exp-box-1)
  1588. X    ; TEST box-2
  1589. X    (tst-achieve-state pre-box)
  1590. X    (box-region t)
  1591. X    (tst-capture-state 'post-state)
  1592. X    (tst-equ-state post-state exp-box-2)
  1593. X    ; TEST unbox-1
  1594. X    (tst-achieve-state pre-unbox)
  1595. X    (unbox nil)
  1596. X    (tst-capture-state 'post-state)
  1597. X    (tst-equ-state post-state exp-unbox-1)
  1598. X    ; TEST unbox-2
  1599. X    (tst-achieve-state pre-unbox)
  1600. X    (unbox t)
  1601. X    (tst-capture-state 'post-state)
  1602. X    (tst-equ-state post-state exp-unbox-2)
  1603. X                                        ; Results of tests
  1604. X    (set-buffer "*equal-log*")
  1605. X    (save-file "equal-log-sample")
  1606. X                                        ; Analysis of testing
  1607. X    (tst-analyze)
  1608. X    (tst-display-batch)
  1609. X    ) ; let
  1610. X) ; defun script
  1611. X@end example
  1612. X
  1613. X@section Batch Invocation of Test
  1614. X
  1615. XTo invoke the test script from batch, use the following Unix command:
  1616. X@example
  1617. X% gnuemacs -batch -l script.el -f script -kill &
  1618. X@end example
  1619. XNote that the test script explicitly loads ``test.el'' at the beginning
  1620. Xof ``script.el''.
  1621. X
  1622. X
  1623. XAn instrumented package runs considerably slower than an uninstrumented
  1624. Xpackage.  It is a good idea to test your script without instrumentation
  1625. X(and probably without many of the tests).  Once you are satisfied with the
  1626. Xscript, run it at lower priority and/or at non-peak hours to avoid
  1627. Xinconveniencing other users.
  1628. X
  1629. X@section Advanced Batch Use -- Filtering
  1630. X
  1631. XThe state information available for ``capture'ing and ``achieve''ing is
  1632. Xusually more than needed for any particular test.  You can improve the
  1633. Xperformance of testing by filtering out the unneeded components of states.
  1634. XThere are mechanisms for doing this before and after testing:
  1635. X@itemize @bullet
  1636. X@item
  1637. XThe ``capture'' functions use global options to determine the
  1638. Xcomponents to capture.
  1639. X@item
  1640. XThe ``achieve'' functions are similarly parameterized.
  1641. X@item
  1642. XThe ``equality'' functions use global options to determine which components
  1643. Xto compare.  Also, they can be weakened (i.e. return ``true'' more often)
  1644. Xthrough the use of hooks and replacement functions.
  1645. X@item
  1646. XThe ``analysis'' functions reduce the instrumentation data to two special
  1647. Xcases: lack of evaluation and ``constant value across testing''.
  1648. X@item
  1649. XThe ``*equal-log*'' buffer may be viewed in ``outline'' mode, with
  1650. Xuninteresting cases suppressed through elision.
  1651. X@item
  1652. XThe batch display function produces output that may be viewed with the
  1653. X``next-error'' function of ``compilation''.
  1654. X@end itemize
  1655. XIn using these filters you should be aware that too much filtering defeats
  1656. Xthe purpose of testing.
  1657. X
  1658. X@node epilogue, example, running, top
  1659. X@chapter The Epilogue
  1660. X
  1661. X@section How to Extend the Package
  1662. X
  1663. X@subsection Equality Tests
  1664. X
  1665. XIf you want to extend the equality package to compare other aspects of your
  1666. Xenvironment, simply write your own comparison function and add it to the
  1667. X'function-vector' for the appropriate area.  For example, if you were
  1668. Xinterested in comparing the @code{foobar} attribute of buffers, first write
  1669. Xa function, @code{tst-equ-foobar}, and then add it to the list of functions
  1670. Xexecuted for a buffer, @code{tst-equ-buff-state-functions}.
  1671. X
  1672. XSimilarly, if you wanted to test the @code{foo} attribute of a state, add
  1673. Xthe new function to the list of functions executed for a state,
  1674. X@code{tst-equ-state-functions}.
  1675. X
  1676. XYou can also extend the equality tests by the use of hooks.  The method is
  1677. Xdefined in more detail in the section on Inequality.
  1678. X
  1679. X@subsection Instrumentation
  1680. X
  1681. X@subsection Display Functions
  1682. X
  1683. XThe interactive display mode attempts to provide the fiction of annotation
  1684. Xwindows which are part of the code window.  In retrospect it may be that
  1685. Xsimply inserting the text into a new buffer along with the code would be as
  1686. Xuseful.  It also may be that the batch style report in conjunction with the
  1687. X``compilation'' error parsing is just as useful in practice.
  1688. X
  1689. XThere are certainly other types of annotation which could usefully be
  1690. Xdisplayed, like the number of times each line was executed, etc.
  1691. X
  1692. XIt might make sense to bind @samp{tst-display-batch} to a key in
  1693. X@code{test-mode}.  It also might make sense to remove the binding for
  1694. X@code{tst-analyze} and call it only from within the display functions.
  1695. X
  1696. X@subsection Annotation Functions
  1697. X
  1698. XThe annotation database is accessed twice every time an instrumented line
  1699. Xof code is evaluated.  This code contributed substantially to the slow-down
  1700. Xof instrumented code and time spent making it more efficient would be
  1701. Xrewarding.
  1702. X
  1703. X@subsection Analysis Functions
  1704. X
  1705. XIf you want to add further functions to the Analysis Package, you will have
  1706. Xto modify the main function, ``tst-analyze'', which invokes the individual
  1707. Xanalysis functions.  It currently invokes ``tst-anl-zero-counts'' and
  1708. X``tst-anl-constant-values''.  Your new function should use the same idiom
  1709. Xas these functions, i.e., use ``tst-ann-get-lines'' to retrieve the list of
  1710. Xlines for which annotation holds information and then use ``mapcar'' to
  1711. Xapply your single line analysis function to each line's data.  You can then
  1712. Xuse ``tst-ann-put'' to store your results.
  1713. X
  1714. X@node example, , epilogue, top
  1715. X@appendix The Complete Example
  1716. X@include example
  1717. SHAR_EOF
  1718. if test 60887 -ne "`wc -c < 'test.texinfo'`"
  1719. then
  1720.     echo shar: "error transmitting 'test.texinfo'" '(should have been 60887 characters)'
  1721. fi
  1722. fi
  1723. exit 0
  1724. #    End of shell archive
  1725.  
  1726.  
  1727. -- 
  1728.  
  1729. Rich $alz
  1730. Cronus Project, BBN Labs            rsalz@bbn.com
  1731. Moderator, comp.sources.unix            sources@uunet.uu.net
  1732.